package org.springframework.aop.framework.autoproxy;

import com.nanbei.a14.Target;
import org.aopalliance.intercept.MethodInterceptor;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.Order;

import java.util.List;

/**
 * @ClassDescription: AnnotationAwareAspectJAutoProxyCreator Bean后处理器
 * @JdkVersion: 1.8
 * @Author: libs
 * @Created: 2024/11/19 15:43
 */
public class A17 {

        /*
            a.代理的创建时机
                1.初始化之后(无循环依赖时)
                2.实例创建后，依赖注入前(有循环依赖时)，并暂存于二级缓存
            b.依赖注入与初始化不应该被增强，仍应被施加于原始对象
         */

    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("aspectJ", AspectJ.class);
        context.registerBean("advisorConfig", AdvisorConfig.class);
        context.registerBean(ConfigurationClassPostProcessor.class);
        context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
        context.refresh();

        /*
               第一个重要方法 findEligibleAdvisors  根据目标找到有【资格】的Advisors
                a:有【资格】的 Advisor 一部分是低级的，可以由自己编写，如下例中的 advisor
                b:有【资格】的Advisor 另一部分是高级的，由本章的主角解析@Aspect 后获得
         */

        AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
        List<Advisor> target1 = creator.findEligibleAdvisors(Target1.class, "target1");
        /*for (Advisor advisor : target1) {
            System.out.println(advisor);
        }*/

        /*

            第二个重要方法wrapIfNecessary    是否有必要为目标创建代理
                a.它内部调用 findEligibleAdvisors，只要返回集合不空，则表示需要创建代理
         */
        Object o1 = creator.wrapIfNecessary(new Target1(), "target1", "target1");
        System.out.println(o1.getClass());
        Object o2 = creator.wrapIfNecessary(new Target2(), "target2", "target2");
        System.out.println(o2.getClass());

        Target1 o11 = (Target1) o1;
        o11.foo();




    }


    static class Target1 {
        public void foo() {
            System.out.println("target1 foo");
        }
    }

    static class Target2 {
        public void bar() {
            System.out.println("target2 bar");
        }
    }

    @Aspect
    @Order(2)
    static class AspectJ{

        @Before("execution(* foo())")
        public void before(){
            System.out.println("AspectJ before...");
        }

        @After("execution(* foo())")
        public void after(){
            System.out.println("AspectJ after...");
        }
    }


    @Configuration
    static class AdvisorConfig{
        // 创建切面
        @Bean
        public Advisor advisor(MethodInterceptor advice){
            // 设置切入点
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution(* foo())");
            DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
            advisor.setOrder(2);
            return advisor;
        }

        // 创建通知
        @Bean
        public MethodInterceptor advice(){
            return invocation -> {
                System.out.println("Advisor before...");
                Object proceed = invocation.proceed();
                System.out.println("Advisor after...");
                return proceed;
            };
        }
    }
}
